package com.ruicar.afs.cloud.manage.common.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.api.dto.BasicMainInfoDto;
import com.ruicar.afs.cloud.basic.api.dto.ManageOverpaymentDifferenceDto;
import com.ruicar.afs.cloud.basic.api.fegin.info.BasicInfoFeign;
import com.ruicar.afs.cloud.bizcommon.voucher.service.VoucherFlowService;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.constant.VoucherBuriedPointNo;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.modules.dto.mq.voucher.VoucherFlowInfoDto;
import com.ruicar.afs.cloud.common.modules.enums.BusinessType;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.api.feign.info.BasicMainInfoFeign;
import com.ruicar.afs.cloud.manage.cms.service.IcosToCmsChangeRepaymentService;
import com.ruicar.afs.cloud.manage.common.entity.ManageOverpaymentDifference;
import com.ruicar.afs.cloud.manage.common.mapper.ManageOverpaymentDifferenceMapper;
import com.ruicar.afs.cloud.manage.common.service.ManageOverpaymentDifferenceService;
import com.ruicar.afs.cloud.manage.common.util.CreatCaseNoUtil;
import com.ruicar.afs.cloud.manage.common.vo.ContractCloseManageVO;
import com.ruicar.afs.cloud.manage.workflow.entity.WorkTaskCreatedInfo;
import com.ruicar.afs.cloud.manage.workflow.enums.NormalSubmitEnum;
import com.ruicar.afs.cloud.manage.workflow.enums.WorkflowTypeEnum;
import com.ruicar.afs.cloud.manage.workflow.processor.ContractWorkFlowSaveApproveInfoProcessor;
import com.ruicar.afs.cloud.manage.workflow.service.WorkTaskCreatedInfoService;
import com.ruicar.afs.cloud.manage.workflow.service.WorkflowSubmitService;
import com.ruicar.afs.cloud.manage.workflow.vo.TaskSubmitVO;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.StartFlowRequest;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;

/**
 * @author: Lee
 * @date 2020-05-30 04:45:15
 * @description
 */
@Slf4j
@Service
@AllArgsConstructor
public class ManageOverpaymentDifferenceServiceImpl extends ServiceImpl<ManageOverpaymentDifferenceMapper, ManageOverpaymentDifference> implements ManageOverpaymentDifferenceService {

    private final ContractWorkFlowSaveApproveInfoProcessor saveApproveInfoProcessor;
    private final WorkTaskCreatedInfoService workTaskCreatedInfoService;
    private final WorkflowSubmitService workflowSubmitService;
    private final VoucherFlowService voucherFlowService;
    private final WorkflowService workflowService;
    private final BasicInfoFeign basicInfoFeign;
    private final BasicMainInfoFeign basicMainInfoFeign;
    private final IcosToCmsChangeRepaymentService icosToCmsChangeRepaymentService;

    @Override
    public void submitOverpayment(ContractCloseManageVO difference) {
        if (EmptyUtils.isEmpty(difference.getCaseNo())) {
            // 生成案件编号
            difference.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.overpayment));
        }
        if (ProcessModeEnum.reduction.equals(difference.getProcessMode())) {
            difference.setProcessStatus(ProcessStatusEnum.approved);
            difference.setRequestDate(DateUtil.date());
            updateById(difference);
            //发送凭证流水
            handleVoucher(difference);
        } else {
            //提交审核，发起流程
            if (ProcessStatusEnum.draft.equals(difference.getProcessStatus())) {
                difference.setProcessStatus(ProcessStatusEnum.underReview);
                difference.setRequestDate(DateUtil.date());
                updateById(difference);
                //保存合同信息变更申请记录
                //保存待办任务记录
                saveApproveInfoProcessor.saveApproveInfo(difference, ContractBusinessEnum.overpayment,
                        CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.CONTRACT_CLOSE);
                StartFlowRequest startFlowRequest = new StartFlowRequest();
                startFlowRequest.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.CONTRACT_OVERPAYMENT));
                startFlowRequest.setBizDataId(String.valueOf(difference.getId()));
                startFlowRequest.setFlowName((StringUtils.isEmpty(difference.getCustName()) ? "" : (difference.getCustName()) + "-") + AfsEnumUtil.desc(WorkflowTypeEnum.CONTRACT_OVERPAYMENT));
                String json = JSONObject.toJSONString(difference);
                JSONObject cancelJson = JSONObject.parseObject(json);
                //保存审批记录
                TaskSubmitVO vo = new TaskSubmitVO();
                vo.setBizData(cancelJson);
                workflowSubmitService.saveRecord(vo, AfsEnumUtil.desc(NormalSubmitEnum.SUGGEST_CHECK_FINAL));
                //开始流程
                workflowService.startWorkFlow(startFlowRequest, cancelJson);
            } else {
                //更新状态
                difference.setProcessStatus(ProcessStatusEnum.repairedUnderReview);
                updateById(difference);
                //保存待办任务记录
                saveApproveInfoProcessor.saveApproveInfo(difference, ContractBusinessEnum.overpayment,
                        CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.CONTRACT_CLOSE);
                //流程审批
                TaskSubmitVO vo = new TaskSubmitVO();
                String json = JSONObject.toJSONString(difference);
                JSONObject cancelJson = JSONObject.parseObject(json);
                vo.setBizData(cancelJson);
                vo.setApprovalOperating(difference.getApprovalOperating());
                vo.setApprovalOpinion(difference.getApprovalOpinion());
                vo.setReasonType(difference.getReasonType());
                workflowSubmitService.submit(vo);
            }
        }
    }

    @Override
    public String approveOverpayment(ContractCloseManageVO difference) {
        CaseStatusEnum CaseStatus;
        ProcessStatusEnum processStatus;

        //更新处理状态
        if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_CHECK_FINAL).equals(difference.getApprovalOperating())) {
            WorkTaskCreatedInfo workTaskCreatedInfo = workTaskCreatedInfoService.getOne(Wrappers.<WorkTaskCreatedInfo>query().lambda()
                    .eq(WorkTaskCreatedInfo::getBizDataId, String.valueOf(difference.getId())));
            if (ProcessStatusEnum.approved.name().equals(workTaskCreatedInfo.getTaskMemo())) {
                CaseStatus = CaseStatusEnum.APPROVED;
                processStatus = ProcessStatusEnum.approved;
                difference.setEndDate(DateUtil.date());
                if (!difference.getContractStatus().equals(ContractStatusEnum.contractCancel)) {
                    ManageOverpaymentDifferenceDto overpaymentDifferenceDto = new ManageOverpaymentDifferenceDto();
                    BeanUtils.copyProperties(difference, overpaymentDifferenceDto);
                    IResponse<String> result = basicInfoFeign.updateReceiptRecord(overpaymentDifferenceDto);
                    if (!Boolean.TRUE.toString().equals(result.getData())) {
                        return result.getData();
                    }
                }
                handleVoucher(difference);
            } else if (ProcessStatusEnum.repairedUnderReview.equals(difference.getProcessStatus())) {
                CaseStatus = CaseStatusEnum.UNDER_REVIEW;
                processStatus = ProcessStatusEnum.repairedUnderReview;
            } else {
                CaseStatus = CaseStatusEnum.UNDER_REVIEW;
                processStatus = ProcessStatusEnum.underReview;
            }
            difference.setProcessStatus(processStatus);
            //保存待办任务记录
            //保存合同信息变更申请记录
            saveApproveInfoProcessor.saveApproveInfo(difference, ContractBusinessEnum.overpayment,
                    CaseStatus, BusinessUrlEnum.CONTRACT_CLOSE);
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_REJECT_FINAL).equals(difference.getApprovalOperating())) {
            difference.setEndDate(DateUtil.date());
            difference.setProcessStatus(ProcessStatusEnum.refuse);
            difference.setEndDate(DateUtil.date());
            //保存合同信息变更申请记录
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(difference, ContractBusinessEnum.overpayment,
                    CaseStatusEnum.REFUSE, BusinessUrlEnum.CONTRACT_CLOSE);
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SEND_BACK).equals(difference.getApprovalOperating())) {
            WorkTaskCreatedInfo workTaskCreatedInfo = workTaskCreatedInfoService.getOne(Wrappers.<WorkTaskCreatedInfo>query().lambda()
                    .eq(WorkTaskCreatedInfo::getBizDataId, String.valueOf(difference.getId())));
            if (ProcessStatusEnum.toBeRepaired.name().equals(workTaskCreatedInfo.getTaskMemo())) {
                difference.setProcessStatus(ProcessStatusEnum.toBeRepaired);
            }
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(difference, ContractBusinessEnum.overpayment,
                    CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.CONTRACT_CLOSE);
        }
        updateById(difference);

        //流程审批
        TaskSubmitVO vo = new TaskSubmitVO();
        String json = JSONObject.toJSONString(difference);
        JSONObject cancelJson = JSONObject.parseObject(json);
        vo.setBizData(cancelJson);
        vo.setApprovalOperating(difference.getApprovalOperating());
        vo.setApprovalOpinion(difference.getApprovalOpinion());
        vo.setReasonType(difference.getReasonType());
        workflowSubmitService.submit(vo);
        return null;
    }

    @Override
    public IPage getContractCloseList(Page page, ContractCloseManageVO vo) {
        return this.baseMapper.getContractCloseList(page, vo);
    }

    @Override
    public void closeContract(ManageOverpaymentDifference difference) {
        //step2： 获取当前日结日期
        IResponse<String> batchDate = null;
        if (DataSourceEnum.icos == difference.getDataSource()){
            batchDate = basicMainInfoFeign.closeContract(difference.getContractNo());
            if (CommonConstants.FAIL.equals(batchDate.getCode())) {
                throw new AfsBaseException("还款日变更结果数据推送至basic服务失败，请重试！");
            }
        }else {
//            CmsBaseResponseDTO response = icosToCmsChangeRepaymentService.syncToCmsContractCloseResult(difference);
//            if (AfsEnumUtil.key(SuccessResponseEnum.FAIL).equals(response.getSuccess()) && !AfsEnumUtil.key(CodeResponseEnum.M10051).equals(response.getCode())) {
//                throw new AfsBaseException("还款日变更结果数据推送至cms系统失败，请重试！");
//            }
        }


        DateTime batchDates = DateUtil.parse(batchDate.getData());
        difference.setCloseDate(batchDates);
        updateById(difference);
        VoucherFlowInfoDto voucherFlowInfoDto = new VoucherFlowInfoDto();
        voucherFlowInfoDto.setBuriedPointNo(VoucherBuriedPointNo.contractExpire);
        voucherFlowInfoDto.setContractNo(difference.getContractNo());
        voucherFlowInfoDto.setKeepAccountDate(new Date());
        voucherFlowInfoDto.setTransNo(difference.getContractNo());
        IResponse<BasicMainInfoDto> dto = basicInfoFeign.mainInfofindByContractNo(difference.getContractNo());
        if (CommonConstants.SUCCESS.equals(dto.getCode())) {
            BasicMainInfoDto basicMainInfoDto = dto.getData();
            voucherFlowInfoDto.setBusinessType((BusinessType) AfsEnumUtil
                    .getEnum(AfsEnumUtil.key(basicMainInfoDto.getBusinessType()), BusinessType.class));
            voucherFlowInfoDto.setFinancialProducts(basicMainInfoDto.getProductName());
            voucherFlowInfoDto.setDealerName(basicMainInfoDto.getChannelName());
        } else {
            Assert.isTrue(false, "获取合同基本信息有误!");
        }
        log.info("合同号:{}，埋点号:{}，合同关闭===开始保存流水", voucherFlowInfoDto.getBuriedPointNo(), voucherFlowInfoDto.getContractNo());
        voucherFlowService.sendFlow(voucherFlowInfoDto);
        log.info("合同号:{}，埋点号:{}，合同关闭===结束保存流水", voucherFlowInfoDto.getBuriedPointNo(), voucherFlowInfoDto.getContractNo());

    }

    @Override
    public IResponse delete(String contractNo) {
        ManageOverpaymentDifference manageOverpaymentDifference = this.getOne(Wrappers.<ManageOverpaymentDifference>lambdaQuery().eq(ManageOverpaymentDifference::getContractNo, contractNo));
        if (EmptyUtils.isNotEmpty(manageOverpaymentDifference) && EmptyUtils.isNotEmpty(manageOverpaymentDifference.getCloseDate())) {
            return new IResponse().fail("合同已关闭成功！");
        }
        boolean result = this.remove(Wrappers.<ManageOverpaymentDifference>lambdaQuery().eq(ManageOverpaymentDifference::getContractNo, contractNo));
        if (result) {
            return new IResponse().success("删除成功");
        } else {
            return new IResponse().fail("删除失败");
        }
    }

    private void handleVoucher(ManageOverpaymentDifference difference) {
        VoucherFlowInfoDto voucherFlowInfoDto = new VoucherFlowInfoDto();
        voucherFlowInfoDto.setBuriedPointNo(VoucherBuriedPointNo.advancePaymentProcessing);
        voucherFlowInfoDto.setContractNo(difference.getContractNo());
        voucherFlowInfoDto.setKeepAccountDate(new Date());
        voucherFlowInfoDto.setTransNo(difference.getContractNo());
        IResponse<BasicMainInfoDto> dto = basicInfoFeign.mainInfofindByContractNo(difference.getContractNo());
        if (CommonConstants.SUCCESS.equals(dto.getCode())) {
            BasicMainInfoDto basicMainInfoDto = dto.getData();
            voucherFlowInfoDto.setBusinessType((BusinessType) AfsEnumUtil
                    .getEnum(AfsEnumUtil.key(basicMainInfoDto.getBusinessType()), BusinessType.class));
            voucherFlowInfoDto.setFinancialProducts(basicMainInfoDto.getProductName());
            voucherFlowInfoDto.setDealerName(basicMainInfoDto.getChannelName());
        } else {
            Assert.isTrue(false, "获取合同基本信息有误!");
        }
        log.info("合同号:{}，埋点号:{}，合同关闭===开始保存流水", voucherFlowInfoDto.getBuriedPointNo(), voucherFlowInfoDto.getContractNo());
        voucherFlowService.sendFlow(voucherFlowInfoDto);
        log.info("合同号:{}，埋点号:{}，合同关闭===结束保存流水", voucherFlowInfoDto.getBuriedPointNo(), voucherFlowInfoDto.getContractNo());

    }
}
